from flask import Response, jsonify, Flask, request, Blueprint
from configs import *
import os
import shutil
from modules.Tables import *


# 递归查找 parent_id 直到为空  向上找
def get_folder_names_recursive(folder_id, folder_names=[]):
    # 查询数据库中指定ID的文件夹信息
    folder = db.session.query(Folder).filter_by(id=folder_id).first()
    if folder is not None:
        folder_names.append(folder.folder_name)  # 将文件夹名字插入到列表
        if folder.folder_parent_id is not None:
            # 如果有父文件夹，继续递归查找
            get_folder_names_recursive(folder.folder_parent_id, folder_names)


# 递归查找 parent_id 直到没有 向下找
def find_folders_with_parent_id(parent_id):
    # 初始化一个空列表用于存储文件夹数据
    folders = []

    # 查询具有特定 folder_parent_id 的数据
    folders_with_parent_id = db.session.query(Folder).filter(Folder.folder_parent_id == parent_id).all()

    for folder in folders_with_parent_id:
        # 将数据添加到列表
        folders.append(folder)

        # 递归查找子文件夹的数据
        child_folders = find_folders_with_parent_id(folder.id)
        folders.extend(child_folders)

    return folders

# 从parent_id为none主节点开始找
def build_tree(data, parent_id=None):
    tree = []
    for item in data:
        if item['folder_parent_id'] == parent_id:
            children = build_tree(data, item['id'])
            if children:
                item['children'] = children
            tree.append(item)
    return tree


# 创建蓝图，对应的register目录
imageblue = Blueprint('imageblue', __name__)


@imageblue.route('/select_type', methods=['GET', 'POST', 'DELETE', 'PUT', 'CATCH'])
def select_type():
    # 获取type类型
    type = request.args.get("type", None)
    # 当tyep 为 1 的时候运行敞车程序
    if int(type) == 1:
        # image_list = DeleteRepeat('static/one/open_car/98')
        image_list = []
        return jsonify({'code': 200, 'list': image_list, 'count': len(image_list)})
    # 当tyep 为 2 的时候运行集装箱程序
    elif int(type) == 2:
        # image_list = main('static/container')
        image_list = []
        return jsonify({'code': 200, 'list': image_list, 'count': len(image_list)})


# 创建文件夹接口
@imageblue.route('/file_mkdir', methods=['POST'])
def file_mkdir():
    # 获取当前文件夹所在路径   如果没有则为第一层
    file_path = request.form.get('file_path', None)

    # 获取创建文件夹名字
    file_name = request.form.get('file_name', None)

    # 标识符表示文件的增加跟删除  当为1的时候调用增加方法， 当为2的时候调用删除文件夹方法
    file_type = request.form.get( 'file_type', None)

    # 当为1的时候调用增加方法
    if file_type == '1':

        # 当有路径的时候在路径下边创建文件夹
        if file_path:

            # 查找路径id
            folder_id = db.session.query(Folder).filter(Folder.folder_name == file_path).all()

            # 如果数据表里查到名字相同文件夹，那么当前文件夹为子文件夹
            if folder_id:

                # 查找数据
                # 如果名称相同且有parent_id   那么数据不写入
                # 如果名称相同且parent_id为空 进行写入操作
                folder_info = db.session.query(Folder).filter(Folder.folder_name==file_name).first()

                if folder_info == None :

                    # 数据添加
                    folder_res = Folder(folder_name=file_name, folder_parent_id=folder_id[-1].id, )
                    # 在会话中执行插入操作
                    db.session.add(folder_res)
                    db.session.commit()

                    # 递归找出父文件名字，组成目录与数据表文件表联动
                    folder_names = []
                    get_folder_names_recursive(folder_res.id, folder_names)
                    folder_names.reverse()  # 将列表反转以获取正确的顺序
                    list_dir = "/".join(folder_names[0:-1])

                    # 如果有给定路径，则在该路径下创建文件夹
                    new_folder_path = os.path.join(FILE_SAVE_PATH, list_dir, file_name)
                    os.makedirs(new_folder_path, exist_ok=True)

                else:

                    return jsonify({'code': 400, 'msg': '文件夹名称重复！'})

                return jsonify({'code': 200, 'msg': '文件夹创建成功'})

            else:
                # 如果没有查到相同文件夹 返回没有父文件夹
                return jsonify({'code': 400, 'msg': '父文件夹不存在'})
        # 否则创建第一个文件夹
        else:

            # 数据库写入第一个父文件夹
            # 创建一个模型对象并设置属性值
            folder_res = Folder(folder_name=file_name)
            # 在会话中执行插入操作
            db.session.add(folder_res)
            db.session.commit()

            # 否则，在默认的 Static目录下创建文件夹
            default_folder_path = os.path.join(FILE_SAVE_PATH, file_name)
            os.makedirs(default_folder_path, exist_ok=True)

            return jsonify({'code': 200, 'msg': '创建成功'})

    # 当为2的时候调用删除文件夹方法
    else:

        # 当有路径的时候 删除第一层之下的文件夹
        if file_path:

            # 查找路径id
            folder_id = db.session.query(Folder).filter(Folder.folder_name == file_path).all()

            # 递归找出父文件名字，组成目录与数据表文件表联动
            folder_names = []
            get_folder_names_recursive(folder_id[-1].folder_parent_id, folder_names)
            folder_names.reverse()  # 将列表反转以获取正确的顺序
            # 因为是文件夹删除所以加自身，删除file_name
            list_dir = "/".join(folder_names) + '/' + folder_id[-1].folder_name

            # 删除中间级别目录以及递归查找目录之下文件
            folder_id_id = db.session.query(Folder).filter(Folder.folder_name == file_name).first()

            # 当查找到相同文件
            if folder_id_id:
                # 递归查找要删除的文件目录id以及下级id
                result_folders = find_folders_with_parent_id(folder_id_id.id)
                folder_list = [i.id for i in result_folders]
                folder_list.append(folder_id_id.id)
                db.session.commit()
                # 文件目录id以及下级id数据表删除
                db.session.query(Folder).filter(Folder.id.in_(folder_list)).delete(synchronize_session=False)

                # 数据库删除文件夹
                db.session.query(Folder).filter(Folder.folder_name == file_name).delete()
                db.session.commit()

                # 删除指定路径下的文件夹及其内容
                folder_to_deletes1 = os.path.join(FILE_SAVE_PATH + list_dir, file_name)

                folder_to_deletes2 = os.path.join(FILE_SAVE_PATH, list_dir, file_name)

                shutil.rmtree(folder_to_deletes1, ignore_errors=True)
                shutil.rmtree(folder_to_deletes2, ignore_errors=True)

                return jsonify({'code': 200, 'msg': '删除子文件成功'})
            else:
                return jsonify({'code': 400, 'msg': '没用找到对应的主文件夹'})

        # 当没有路径的时候 删除第一层的文件夹
        else:

            # 数据库删除文件夹
            folder_id = db.session.query(Folder).filter(Folder.folder_name == file_name).first()
            if folder_id:
                result_folders = find_folders_with_parent_id(folder_id.id)
                folder_list = [i.id for i in result_folders]
                folder_list.append(folder_id.id)
                db.session.commit()
                db.session.query(Folder).filter(Folder.id.in_(folder_list)).delete(synchronize_session=False)

                # 删除默认路径下的文件夹及其内容
                folder_to_delete = os.path.join(FILE_SAVE_PATH, file_name)
                shutil.rmtree(folder_to_delete, ignore_errors=True)
                return jsonify({'code': 200, 'msg': '删除成功'})
            else:
                return jsonify({'code': 400, 'msg': '没用找到对应的主文件夹'})


# 文件上传接口
@imageblue.route('/file_save', methods=['POST'])
def file_save():
    # 上传类型，是多文件还是单文件
    file_type = request.form.get('type', None)

    # 文件目标文件夹
    file_folder = request.form.get('file_path', None)

    # 当file_type存在
    if file_type:

        # 判断 当file_type类型为1的时候进行单文件上传  为2的时候进行多文件上传
        if file_type == '1':

            # 单个文件接收
            uploaded_file = request.files.get('files')
            # 定义变量为之后赋值做准备
            file_fold = ''

            if uploaded_file:

                # 当有/的时候表示为多层所以取最后一个， 为数据库查找 folder_name 相同字段名称进行图片存储做准备
                if file_folder.count('/') > 0:
                    file_fold = file_folder.split('/')[-1]
                # 没用斜杆的话只是一层
                else:
                    file_fold = file_folder

                # file_name为上传文件名字
                file_name = uploaded_file.filename

                # file_path为 路径/文件名字 （结合）
                file_path = os.path.join(FILE_SAVE_PATH, file_folder, file_name)

                # 文件保存
                uploaded_file.save(file_path)

                # 查找数据库相同 file_fold 字段名称 ， 将文件存储列表写入
                folder_id = db.session.query(Folder).filter(Folder.folder_name == file_fold).first()

                # 当数据库名称匹配到时
                if folder_id:
                    # 当 folder_list不为空时，说明有数据，数据为列表格式字符串
                    if folder_id.folder_list:

                        # 已有数据进行去重写入
                        folder_id.folder_list = str(list(set([file_path.replace('\\', '/').replace(FILE_DELETE_PATH, '')]+eval(folder_id.folder_list))))

                    # 当 folder_list 为空时  构造列表数据写入
                    else:
                        folder_id.folder_list = str([file_path.replace('\\', '/').replace(FILE_DELETE_PATH, '')])
                    # 提交更改到数据库
                    db.session.commit()
                    return jsonify({'code': 200, 'msg': '上传成功'})
                else:
                    return jsonify({'code': 400, 'msg': '没有查到,上传路径名称错误'})

            return jsonify({'code': 400, 'msg': '没有上传文件'})
        else:

            # 多个文件接收
            uploaded_files = request.files.getlist('files')
            # 定义变量为之后赋值做准备
            file_fold = ''
            if uploaded_files:

                # 当有/的时候表示为多层所以取最后一个， 为数据库查找 folder_name 相同字段名称进行图片存储做准备
                if file_folder.count('/') > 0:
                    file_fold = file_folder.split('/')[-1]
                # 没用斜杆的话只是一层
                else:
                    file_fold = file_folder

                # 定义变量接受多个照片写入列表，为后续写入数据库做准备
                folder_list = []

                # 循环文件
                for uploaded_file in uploaded_files:
                    # file_name为上传文件名字
                    file_name = uploaded_file.filename
                    # file_path为 路径/文件名字 （结合）
                    file_path = os.path.join(FILE_SAVE_PATH, file_folder, file_name)
                    # 文件保存
                    uploaded_file.save(file_path)

                    # 将数据添加到列表内 写入数据库
                    folder_list.append(file_path.replace('\\', '/'))


                # 图片列表去除目录前缀
                cleaned_file_paths = [path.replace(FILE_DELETE_PATH, '') for path in folder_list]
                print(cleaned_file_paths,'去重数据')

                # 查找数据库相同 file_fold 字段名称 ， 将文件存储列表写入
                folder_id = db.session.query(Folder).filter(Folder.folder_name == file_fold).first()
                # 当数据库名称匹配到时
                if folder_id:

                    # 当 folder_list不为空时，说明有数据，数据为列表格式字符串
                    if folder_id.folder_list:

                        # 已有数据进行去重写入
                        folder_id.folder_list = str(list(set(eval(folder_id.folder_list)+cleaned_file_paths)))

                    # 当 folder_list 为空时  构造列表数据写入
                    else:
                        folder_id.folder_list = str(cleaned_file_paths)

                    # 提交更改到数据库
                    db.session.commit()

                    return jsonify({'code': 200, 'msg': '上传成功'})
                else:
                    return jsonify({'code': 400, 'msg': '没有查到,上传路径名称错误'})

            return jsonify({'code': 400, 'msg': '没有上传文件'})
    # 不存在返回值
    else:
        return jsonify({'code': 400, 'msg': '请选择参数'})



# 数据表数据返回接口
@imageblue.route('/folder_info', methods=['POST','GET'])
def folder_info():
    # 查询文件表所有数据
    folder_res = db.session.query(Folder).all()
    if folder_res:
        # 转换为套字典的列表
        folder_dict_list = convert_folder_to_dict_list(folder_res,['create_time','folder_list','folder_parent_id','folder_name','id'])
        # 调用方法来寻找节点返回数据
        folder_dict_list = build_tree(folder_dict_list)
        print(folder_dict_list)

        return  jsonify({'code': 200, 'data':folder_dict_list})
    return jsonify({'code': 400, 'msg':'文件表数据为空'})


